package ro.upt.ac.cstaicu.instrumentation.classadapters;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;

import ro.upt.ac.cstaicu.analyze.Entity;
import ro.upt.ac.cstaicu.instrumentation.methodadapters.IMMethodAdapter;

public abstract class IMClassAdapter extends CustomClassAdapter {

	private String className;
	protected HashMap<String, IMMethodAdapter> adapters = new HashMap<String, IMMethodAdapter>();

	public IMClassAdapter(ClassVisitor cv) {

		super(cv);
		IMMethodAdapter.resetPredicateClassCounter();

	}

	public void visit(int arg0, int arg1, String arg2, String arg3,
			String arg4, String[] arg5) {
		className = arg2.replace("/", ".");
		super.visit(arg0, arg1, arg2, arg3, arg4, arg5);
	}

	/**
	 * This method is called every time the ClassReader finds a call to a method in the original bytecode.
	 * A request is send to the ClassWriter to create a MehtodVisitor. This visitor is wrapped in a custom
	 * adapter witch will be returned by the function.
	 *
	 */
	public MethodVisitor visitMethod(int access, String name, String desc,
			String signature, String[] exceptions) {

		MethodVisitor adapter;
		MethodVisitor visitor =
			cv.visitMethod(access, name, desc, signature, exceptions);

		adapter = getMethodAdapter(visitor, className, name);
		
		return adapter;

	}

	protected abstract MethodVisitor getMethodAdapter(MethodVisitor visitor, String className, String methodName);
	
	public Collection<Entity> getTracedPredicates() {
		Collection<Entity> result = new ArrayList<Entity>();
		for (String className : adapters.keySet()) {
//			result.put(className, adapters.get(className).getPredicates());
			result.addAll(adapters.get(className).getPredicates());
		}
		return result;
	}
}
